#pragma once
#include<iostream>

namespace wyl
{
	template<class T>
	class unique_ptr
	{
	public:
		unique_ptr(T* ptr = nullptr) :_ptr(ptr) {}
		~unique_ptr()
		{
			delete _ptr;
			std::cout << "~unique_ptr()" << std::endl;
		}

		T* Get()
		{
			return _ptr;
		}

	private:
		unique_ptr<T>& operator=(const unique_ptr<T>&);
		unique_ptr(const unique_ptr<T>&);
	private:
		T* _ptr;

	};

	void unique_ptr_test()
	{
		unique_ptr<int> up1(new int(5)
		);
		std::cout << *up1.Get() << std::endl;
	}

	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr = nullptr) : _ptr(ptr) , _pcount(new int(1)){}
		shared_ptr(const shared_ptr<T>& sp)
			:_ptr(sp._ptr),_pcount(sp._pcount)
		{
			(*_pcount)++;
		}

		T* operator->()
		{
			return _ptr;
		}
		T& operator*()
		{
			return *_ptr;
		}

		shared_ptr& operator=(const shared_ptr<T>& sp)
		{
			if (sp._ptr == _ptr) return *this; 
			
			if (--(*_pcount) == 0)
			{
				delete _ptr;
				delete _pcount; 
			}
			_pcount = sp._pcount; 
			_ptr = sp._ptr;
			(*_pcount)++;
			return *this;
		}

		~shared_ptr()
		{
			std::cout << "~shared_ptr()   p_count = " << *_pcount << std::endl;
			if (--(*_pcount) == 0)
			{
				delete _ptr;
				delete _pcount;
			}
		}
 
	private:
		int* _pcount; 
		T* _ptr;
	};

	void shared_ptr_test()
	{
		shared_ptr<int> sp1(new int(5)); 
		shared_ptr<int> sp2(sp1);
		shared_ptr<int> sp3;
		sp3 = sp2;

	}

}